home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / xlib / ttri.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  15KB  |  643 lines

  1. /*
  2.  * (c) Copyright 1993-94, Silicon Graphics, Inc.
  3.  * ALL RIGHTS RESERVED
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software for
  6.  * any purpose and without fee is hereby granted, provided that the above
  7.  * copyright notice appear in all copies and that both the copyright notice
  8.  * and this permission notice appear in supporting documentation, and that
  9.  * the name of Silicon Graphics, Inc. not be used in advertising
  10.  * or publicity pertaining to distribution of the software without specific,
  11.  * written prior permission.
  12.  *
  13.  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  14.  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  15.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  16.  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
  17.  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  18.  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  19.  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  20.  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  21.  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
  22.  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  23.  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  24.  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  25.  *
  26.  * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND
  27.  * Use, duplication, or disclosure by the Government is subject to
  28.  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  29.  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  30.  * clause at DFARS 252.227-7013 and/or in similar or successor
  31.  * clauses in the FAR or the DOD or NASA FAR Supplement.
  32.  * Unpublished-- rights reserved under the copyright laws of the
  33.  * United States.  Contractor/manufacturer is Silicon Graphics,
  34.  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
  35.  *
  36.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  37.  */
  38. #include <stdio.h>
  39. #include <string.h>
  40. #include <stdlib.h>
  41. #include <GL/gl.h>
  42. #include <GL/glx.h>
  43. #include <GL/glu.h>
  44. #include <X11/keysym.h>
  45.  
  46. static int attributes[] = {
  47.     GLX_DOUBLEBUFFER,
  48.     GLX_RGBA,
  49.     GLX_RED_SIZE, 1,
  50.     GLX_GREEN_SIZE, 1,
  51.     GLX_BLUE_SIZE, 1,
  52.     None,
  53. };
  54.  
  55. #define SETCOLOR(x) (rgb ? glColor3fv(rgbMap[x]) : glIndexf(x))
  56.  
  57. enum {
  58.     BLACK = 0,
  59.     RED,
  60.     GREEN,
  61.     YELLOW,
  62.     BLUE,
  63.     MAGENTA,
  64.     CYAN,
  65.     WHITE
  66. };
  67.  
  68. #define    SOLID 1
  69. #define    LINE 2
  70. #define    POINT 3
  71.  
  72.  
  73. static float rgbMap[8][3] = {
  74.     {0, 0, 0},
  75.     {1, 0, 0},
  76.     {0, 1, 0},
  77.     {1, 1, 0},
  78.     {0, 0, 1},
  79.     {1, 0, 1},
  80.     {0, 1, 1},
  81.     {1, 1, 1}
  82. };
  83.  
  84. static long width = 300, height = 300;
  85. static long needUpdate;
  86. static long rgb = 1;
  87. static long color1, color2, color3;
  88.  
  89. static float zRotation = 90.0;
  90. static float zoom = 1;
  91. static long state = SOLID;
  92. static long showVerticies = 1;
  93. static long hideBottomTriangle = GL_FALSE;
  94. static long dithering = GL_TRUE;
  95. static long outline = GL_TRUE;
  96. static long culling = GL_FALSE;
  97. static long winding = GL_FALSE;
  98. static long face = GL_FALSE;
  99.  
  100. static float boxA[3] = {-100, -100, 0};
  101. static float boxB[3] = { 100, -100, 0};
  102. static float boxC[3] = { 100,  100, 0};
  103. static float boxD[3] = {-100,  100, 0};
  104.  
  105. static float p0[3] = {-125,-80, 0};
  106. static float p1[3] = {-125, 80, 0};
  107. static float p2[3] = { 172,  0, 0};
  108.  
  109.  
  110. static void BeginPrim(void)
  111. {
  112.     switch (state) {
  113.       case SOLID:
  114.     glBegin(GL_POLYGON);
  115.     break;
  116.       case LINE:
  117.     glBegin(GL_LINE_LOOP);
  118.     break;
  119.       case POINT:
  120.     glBegin(GL_POINTS);
  121.     break;
  122.     }
  123. }
  124.  
  125. static void EndPrim(void)
  126. {
  127.     glEnd();
  128. }
  129.  
  130. static void DoDisplay(void)
  131. {
  132.     float xscale, yscale;
  133.  
  134.     (culling) ? glEnable(GL_CULL_FACE) : glDisable(GL_CULL_FACE);
  135.     (winding) ? glFrontFace(GL_CCW) : glFrontFace(GL_CW);
  136.     (face) ? glCullFace(GL_FRONT) : glCullFace(GL_BACK);
  137.  
  138.     glScissor(10, 10, width-20, height-20);
  139.     glEnable(GL_SCISSOR_TEST);
  140.     glViewport(10, 10, width-20, height-20);
  141.     glMatrixMode(GL_PROJECTION);
  142.     glLoadIdentity();
  143.     gluOrtho2D(-175, 175, -175, 175);
  144.     glMatrixMode(GL_MODELVIEW);
  145.     (dithering) ? glEnable(GL_DITHER) : glDisable(GL_DITHER);
  146.  
  147.     glClearColor(0.0, 0.0, 0.0, 0.0);
  148.     glClear(GL_COLOR_BUFFER_BIT);
  149.  
  150.     /* draw clipping box */
  151.     SETCOLOR(GREEN);
  152.     glBegin(GL_LINE_LOOP);
  153.     glVertex3fv(boxA);
  154.     glVertex3fv(boxB);
  155.     glVertex3fv(boxC);
  156.     glVertex3fv(boxD);
  157.     glEnd();
  158.  
  159.     /* draw triangle to show where it sits in relation to clipping box */
  160.     if (!hideBottomTriangle) {
  161.     SETCOLOR(BLUE);
  162.     glPushMatrix();
  163.     glScalef(zoom, zoom, zoom);
  164.     glRotatef(zRotation, 0,0,1);
  165.     BeginPrim();
  166.         glVertex3fv(p0);
  167.         glVertex3fv(p1);
  168.         glVertex3fv(p2);
  169.     EndPrim();
  170.     if (showVerticies) {
  171.         rgb ? glColor3fv(rgbMap[RED]) : glIndexf(color1);
  172.         glRectf(p0[0]-2, p0[1]-2, p0[0]+2, p0[1]+2);
  173.         rgb ? glColor3fv(rgbMap[GREEN]) : glIndexf(color2);
  174.         glRectf(p1[0]-2, p1[1]-2, p1[0]+2, p1[1]+2);
  175.         rgb ? glColor3fv(rgbMap[BLUE]) : glIndexf(color3);
  176.         glRectf(p2[0]-2, p2[1]-2, p2[0]+2, p2[1]+2);
  177.     }
  178.     glPopMatrix();
  179.     }
  180.  
  181.     /* now draw triangle with frustum clipping to clipping box */
  182.     SETCOLOR(RED);
  183.     xscale = (float)(width - 20) / 2 / 175 * (175 - 100) + 10;
  184.     yscale = (float)(height - 20) / 2 / 175 * (175 - 100) + 10;
  185.     glMatrixMode(GL_PROJECTION);
  186.     glLoadIdentity();
  187.     gluOrtho2D(-100, 100, -100, 100);
  188.     glMatrixMode(GL_MODELVIEW);
  189.     glScissor(xscale, yscale, width-2*xscale, height-2*yscale);
  190.     glViewport(xscale, yscale, width-2*xscale, height-2*yscale);
  191.     glPushMatrix();
  192.     glScalef(zoom, zoom, zoom);
  193.     glRotatef(zRotation, 0,0,1);
  194.  
  195.     glEnable(GL_LINE_STIPPLE);
  196.     glLineWidth(5);
  197.     glEnable(GL_POINT_SMOOTH);
  198.     glPointSize(10);
  199.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  200.     BeginPrim();
  201.             rgb ? glColor3fv(rgbMap[RED]) : glIndexf(color1);
  202.         glVertex3fv(p0);
  203.         rgb ? glColor3fv(rgbMap[GREEN]) : glIndexf(color2);
  204.         glVertex3fv(p1);
  205.         rgb ? glColor3fv(rgbMap[BLUE]) : glIndexf(color3);
  206.         glVertex3fv(p2);
  207.     EndPrim();
  208.     glDisable(GL_LINE_STIPPLE);
  209.     glLineWidth(1);
  210.     glDisable(GL_POINT_SMOOTH);
  211.     glPointSize(1);
  212.     glBlendFunc(GL_ONE, GL_ZERO);
  213.  
  214.         if (outline) {
  215.         SETCOLOR(WHITE);
  216.         glBegin(GL_LINE_LOOP);
  217.             glVertex3fv(p0);
  218.             glVertex3fv(p1);
  219.             glVertex3fv(p2);
  220.         glEnd();
  221.         }
  222.     glPopMatrix();
  223.  
  224.     glFlush();
  225.  
  226.     if (needUpdate) {
  227.     printf("%s %s %s\n",
  228.            (culling ? "Culling" : "Not culling"),
  229.            (face ? "front" : "back"),
  230.            (winding ? "ccw" : "cw"));
  231.     needUpdate = 0;
  232.     }
  233. }
  234.  
  235. #if XXX
  236. static void SetColorMap(void)
  237. {
  238.     TK_ColorRec c;
  239.     float percent, percent2;
  240.     long j, i;
  241.     float r, g, b;
  242.  
  243.     for (j = 0; j <= 12; j++) {
  244.     if (j <= 6) {
  245.         percent = j / 6.0;
  246.         r = 1.0 - 0.8 * percent;
  247.         g = 0.2 + 0.8 * percent;
  248.         b = 0.2;
  249.     } else {
  250.         percent = (j - 6) / 6.0;
  251.         r = 0.2;
  252.         g = 1.0 - 0.8 * percent;
  253.         b = 0.2 + 0.8 * percent;
  254.     }
  255.     c.index = j + 18;
  256.     c.r = r;
  257.     c.g = g;
  258.     c.b = b;
  259.     tkSet(TK_CITORGB, (void *)&c);
  260.     for (i = 0; i < 16; i++) {
  261.         percent2 = i / 15.0;
  262.         c.index = j * 16 + i + 32;
  263.         c.r = r * percent2;
  264.         c.g = g * percent2;
  265.         c.b = b * percent2;
  266.         tkSet(TK_CITORGB, (void *)&c);
  267.     }
  268.     }
  269.     color1 = 18;
  270.     color2 = 24;
  271.     color3 = 30;
  272. }
  273. #endif
  274.  
  275. #if XXX
  276. static long Exec(TK_EventRec *ptr)
  277. {
  278.     switch (ptr->event) {
  279.       case TK_EVENT_EXPOSE:
  280.     tkPostEvent(&drawEvent);
  281.     break;
  282.       case TK_EVENT_CONFIG:
  283.     W = ptr->data[TK_WINDOWX];
  284.     H = ptr->data[TK_WINDOWY];
  285.     tkPostEvent(&drawEvent);
  286.     break;
  287.       case TK_EVENT_KEY:
  288.     switch (ptr->data[TK_KEY]) {
  289.       case TK_ESCAPE:
  290.         tkQuit();
  291.       case TK_LEFT:
  292.         zRotation += 0.5;
  293.         tkPostEvent(&drawEvent);
  294.         break;
  295.       case TK_RIGHT:
  296.         zRotation -= 0.5;
  297.         tkPostEvent(&drawEvent);
  298.         break;
  299.       case TK_UP:
  300.         zoom *= 0.75;
  301.         tkPostEvent(&drawEvent);
  302.         break;
  303.       case TK_DOWN:
  304.         zoom /= 0.75;
  305.         if (zoom > 10) {
  306.         zoom = 10;
  307.         }
  308.         tkPostEvent(&drawEvent);
  309.         break;
  310.       case TK_f:
  311.       case TK_F:
  312.         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  313.         tkPostEvent(&drawEvent);
  314.         break;
  315.       case TK_p:
  316.       case TK_P:
  317.         glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
  318.         tkPostEvent(&drawEvent);
  319.         break;
  320.       case TK_l:
  321.       case TK_L:
  322.         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  323.         tkPostEvent(&drawEvent);
  324.         break;
  325.       case TK_1:
  326.         state = SOLID;
  327.         tkPostEvent(&drawEvent);
  328.         break;
  329.       case TK_2:
  330.         state = LINE;
  331.         tkPostEvent(&drawEvent);
  332.         break;
  333.       case TK_3:
  334.         state = POINT;
  335.         tkPostEvent(&drawEvent);
  336.         break;
  337.       case TK_A:
  338.       case TK_a:
  339.         zRotation = 0.0;
  340.         tkPostEvent(&drawEvent);
  341.         break;
  342.       case TK_B:
  343.       case TK_b:
  344.         zRotation = 90.0;
  345.         tkPostEvent(&drawEvent);
  346.         break;
  347.       case TK_C:
  348.       case TK_c:
  349.         zRotation = 180.0;
  350.         tkPostEvent(&drawEvent);
  351.         break;
  352.       case TK_D:
  353.       case TK_d:
  354.         zRotation = 270.0;
  355.         tkPostEvent(&drawEvent);
  356.         break;
  357.       case TK_V:
  358.       case TK_v:
  359.         showVerticies = !showVerticies;
  360.         tkPostEvent(&drawEvent);
  361.         break;
  362.       case TK_s:
  363.       case TK_S:
  364.         glShadeModel(GL_SMOOTH);
  365.         tkPostEvent(&drawEvent);
  366.         break;
  367.       case TK_t:
  368.       case TK_T:
  369.         glShadeModel(GL_FLAT);
  370.         tkPostEvent(&drawEvent);
  371.         break;
  372.       case TK_h:
  373.       case TK_H:
  374.         hideBottomTriangle = !hideBottomTriangle;
  375.         tkPostEvent(&drawEvent);
  376.         break;
  377.       case TK_o:
  378.       case TK_O:
  379.         outline = !outline;
  380.         tkPostEvent(&drawEvent);
  381.         break;
  382.       case TK_m:
  383.       case TK_M:
  384.         dithering = !dithering;
  385.         tkPostEvent(&drawEvent);
  386.         break;
  387.       case TK_7:
  388.         culling = !culling;
  389.         tkPostEvent(&drawEvent);
  390.         needUpdate=1;
  391.         break;
  392.       case TK_8:
  393.         winding = !winding;
  394.         tkPostEvent(&drawEvent);
  395.         needUpdate=1;
  396.         break;
  397.       case TK_9:
  398.         face = !face;
  399.         tkPostEvent(&drawEvent);
  400.         needUpdate=1;
  401.         break;
  402.       case TK_Q:
  403.       case TK_q:
  404.         glEnable(GL_POLYGON_SMOOTH);
  405.         glEnable(GL_BLEND);
  406.         glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  407.         if (!rgb) {
  408.         color1 = 32;
  409.         color2 = 128;
  410.         color3 = 224;
  411.         }
  412.         tkPostEvent(&drawEvent);
  413.         break;
  414.       case TK_W:
  415.       case TK_w:
  416.         glDisable(GL_POLYGON_SMOOTH);
  417.         glDisable(GL_BLEND);
  418.         if (!rgb) {
  419.         color1 = 18;
  420.         color2 = 24;
  421.         color3 = 30;
  422.         }
  423.         tkPostEvent(&drawEvent);
  424.         break;
  425.     }
  426.     break;
  427.       case TK_EVENT_DRAW:
  428.     DoDisplay();
  429.     break;
  430.     }
  431.     return 1;
  432. }
  433. #endif
  434.  
  435. static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
  436. {
  437.     if ((e->type == MapNotify) && (e->xmap.window == (Window)arg)) {
  438.     return GL_TRUE;
  439.     }
  440.     return GL_FALSE;
  441. }
  442.  
  443. int main(int argc, char *argv[])
  444. {
  445.     XVisualInfo *vi;
  446.     Display *dpy;
  447.     Colormap cmap;
  448.     Window window;
  449.     XSetWindowAttributes swa;
  450.     GLXContext cx;
  451.     XEvent event;
  452.     GLboolean needDisplay;
  453.  
  454.     dpy = XOpenDisplay(0);
  455.     if (!dpy) {
  456.     fprintf(stderr, "Can't connect to display \"%s\"\n", getenv("DISPLAY"));
  457.     return -1;
  458.     }
  459.  
  460.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributes);
  461.     if (!vi) {
  462.     fprintf(stderr, "No singlebuffered rgba visual on \"%s\"\n",
  463.         getenv("DISPLAY"));
  464.     return -1;
  465.     }
  466.  
  467.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual,
  468.                AllocNone);
  469.     swa.border_pixel = 0;
  470.     swa.colormap = cmap;
  471.     swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask
  472.     | KeyReleaseMask;
  473.     window = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 10, 10,
  474.                width, height,
  475.                0, vi->depth, InputOutput, vi->visual,
  476.                CWBorderPixel|CWColormap|CWEventMask, &swa);
  477.     XSetStandardProperties(dpy, window, "ttri", "ttri", None, argv, argc, NULL);
  478.     XSetWMColormapWindows(dpy, window, &window, 1);
  479.     XMapWindow(dpy, window);
  480.     XIfEvent(dpy, &event, WaitForMapNotify, (char*)window);
  481.  
  482.     cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
  483.     if (!glXMakeCurrent(dpy, window, cx)) {
  484.     fprintf(stderr, "Can't make window current to context\n");
  485.     return -1;
  486.     }
  487.  
  488.     glLineStipple(1, 0xF0F0);
  489.     needDisplay = GL_TRUE;
  490.     for (;;) {
  491.     do {
  492.         XNextEvent(dpy, &event);
  493.         switch (event.type) {
  494.           case Expose:
  495.         needDisplay = GL_TRUE;
  496.         break;
  497.           case ConfigureNotify:
  498.         width = event.xconfigure.width;
  499.         height = event.xconfigure.height;
  500.         needDisplay = GL_TRUE;
  501.         break;
  502.           case KeyPress:
  503.         {
  504.             char buf[100];
  505.             int rv;
  506.             KeySym ks;
  507.  
  508.             rv = XLookupString(&event.xkey, buf, sizeof(buf), &ks, 0);
  509.             switch (ks) {
  510.               case XK_Left:
  511.             zRotation += 0.5;
  512.             needDisplay = GL_TRUE;
  513.             break;
  514.               case XK_Right:
  515.             zRotation -= 0.5;
  516.             needDisplay = GL_TRUE;
  517.             break;
  518.               case XK_Up:
  519.             zoom *= 0.75;
  520.             needDisplay = GL_TRUE;
  521.             break;
  522.               case XK_Down:
  523.             zoom /= 0.75;
  524.             if (zoom > 10) {
  525.                 zoom = 10;
  526.             }
  527.             needDisplay = GL_TRUE;
  528.             break;
  529.               case XK_f: case XK_F:
  530.             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  531.             needDisplay = GL_TRUE;
  532.             break;
  533.               case XK_p: case XK_P:
  534.             glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
  535.             needDisplay = GL_TRUE;
  536.             break;
  537.               case XK_l: case XK_L:
  538.             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  539.             needDisplay = GL_TRUE;
  540.             break;
  541.               case XK_1:
  542.             state = SOLID;
  543.             needDisplay = GL_TRUE;
  544.             break;
  545.               case XK_2:
  546.             state = LINE;
  547.             needDisplay = GL_TRUE;
  548.             break;
  549.               case XK_3:
  550.             state = POINT;
  551.             needDisplay = GL_TRUE;
  552.             break;
  553.               case XK_A: case XK_a:
  554.             zRotation = 0.0;
  555.             needDisplay = GL_TRUE;
  556.             break;
  557.               case XK_B: case XK_b:
  558.             zRotation = 90.0;
  559.             needDisplay = GL_TRUE;
  560.             break;
  561.               case XK_C: case XK_c:
  562.             zRotation = 180.0;
  563.             needDisplay = GL_TRUE;
  564.             break;
  565.               case XK_D: case XK_d:
  566.             zRotation = 270.0;
  567.             needDisplay = GL_TRUE;
  568.             break;
  569.               case XK_V: case XK_v:
  570.             showVerticies = !showVerticies;
  571.             needDisplay = GL_TRUE;
  572.             break;
  573.               case XK_s: case XK_S:
  574.             glShadeModel(GL_SMOOTH);
  575.             needDisplay = GL_TRUE;
  576.             break;
  577.               case XK_t: case XK_T:
  578.             glShadeModel(GL_FLAT);
  579.             needDisplay = GL_TRUE;
  580.             break;
  581.               case XK_h: case XK_H:
  582.             hideBottomTriangle = !hideBottomTriangle;
  583.             needDisplay = GL_TRUE;
  584.             break;
  585.               case XK_o: case XK_O:
  586.             outline = !outline;
  587.             needDisplay = GL_TRUE;
  588.             break;
  589.               case XK_m: case XK_M:
  590.             dithering = !dithering;
  591.             needDisplay = GL_TRUE;
  592.             break;
  593.               case XK_7:
  594.             culling = !culling;
  595.             needDisplay = GL_TRUE;
  596.             needUpdate=1;
  597.             break;
  598.               case XK_8:
  599.             winding = !winding;
  600.             needDisplay = GL_TRUE;
  601.             needUpdate=1;
  602.             break;
  603.               case XK_9:
  604.             face = !face;
  605.             needDisplay = GL_TRUE;
  606.             needUpdate=1;
  607.             break;
  608.               case XK_Q: case XK_q:
  609.             glEnable(GL_POLYGON_SMOOTH);
  610.             glEnable(GL_BLEND);
  611.             glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  612.             if (!rgb) {
  613.                 color1 = 32;
  614.                 color2 = 128;
  615.                 color3 = 224;
  616.             }
  617.             needDisplay = GL_TRUE;
  618.             break;
  619.               case XK_W: case XK_w:
  620.             glDisable(GL_POLYGON_SMOOTH);
  621.             glDisable(GL_BLEND);
  622.             if (!rgb) {
  623.                 color1 = 18;
  624.                 color2 = 24;
  625.                 color3 = 30;
  626.             }
  627.             needDisplay = GL_TRUE;
  628.             break;
  629.               case XK_Escape:
  630.             return 0;
  631.             }
  632.         }
  633.         break;
  634.         }
  635.     } while (XPending(dpy) != 0);
  636.  
  637.     if (needDisplay) {
  638.         needDisplay = GL_FALSE;
  639.         DoDisplay();
  640.     }
  641.     }
  642. }
  643.